/*
 * @Description:
 * @Version: 1.0
 * @Autor: lzc
 * @Date: 2021-06-28 14:17:27
 * @LastEditors: lzc
 * @LastEditTime: 2021-08-23 17:00:45
 */

#include "GUI.h"
#include <rtthread.h>
#include <rtdevice.h>
#include "drv_gpio.h"
#include "key_deal.h"
#include "startup.h"
#include "flexible_button.h"

/* 单独按键定义方式 */
#define     KEY_0       GET_PIN(1,5)
#define     KEY_1       GET_PIN(5,1)
#define     KEY_2       GET_PIN(3,26)

#define     KEY_UP      GET_PIN(5,0)

/* 矩阵键盘定义方式 */
#define     KEY_SCAN_X1     GET_PIN(3,14)
#define     KEY_SCAN_X2     GET_PIN(3,12)
#define     KEY_SCAN_X3     GET_PIN(3,15)

#define     KEY_SCAN_Y1     GET_PIN(3,17)
#define     KEY_SCAN_Y2     GET_PIN(3,16)

#define     WM_Enable                   1
#define     Matrix_keyboard_Enable      1

extern WM_Status_t WM_Status;
//flex button
// 优点：支持组合按键，支持多次按键的按下的检测。多按键的情况下的实施比较方便
// 缺点：复杂，而且由于是回调类型的可能比较不方便。单个回调。
////////////////////////////////////flex_button/////////////////////////////////////////////////
#define ENUM_TO_STR(e) (#e)
typedef enum
{
    USER_BUTTON_0 = 0, // 对应  的 PIN_KEY0
    USER_BUTTON_1,     // 对应  的 PIN_KEY1
    USER_BUTTON_2,     // 对应  的 PIN_KEY2
    USER_BUTTON_3,     // 对应  的 PIN_WK_UP
    USER_BUTTON_MAX
} user_button_t;

typedef enum
{
    USER_MATRIX_BUTTON_0_Val = 31,           // 对应  的 PIN0
    USER_MATRIX_BUTTON_1_Val = 47,           // 对应  的 PIN1
    USER_MATRIX_BUTTON_2_Val = 55,           // 对应  的 PIN2
    USER_MATRIX_BUTTON_3_Val = 59,           // 对应  的 PIN3
    USER_MATRIX_BUTTON_4_Val = 61,           // 对应  的 PIN4
    USER_MATRIX_BUTTON_5_Val = 62,           // 对应  的 PIN5
    USER_MATRIX_BUTTON_DEFULT_Val = 63  // 对应  的 PIN5
} user_Matrix_button_val_t;

static char *enum_event_string[] =
{
    ENUM_TO_STR(FLEX_BTN_PRESS_DOWN),
    ENUM_TO_STR(FLEX_BTN_PRESS_CLICK),
    ENUM_TO_STR(FLEX_BTN_PRESS_DOUBLE_CLICK),
    ENUM_TO_STR(FLEX_BTN_PRESS_REPEAT_CLICK),
    ENUM_TO_STR(FLEX_BTN_PRESS_SHORT_START),
    ENUM_TO_STR(FLEX_BTN_PRESS_SHORT_UP),
    ENUM_TO_STR(FLEX_BTN_PRESS_LONG_START),
    ENUM_TO_STR(FLEX_BTN_PRESS_LONG_UP),
    ENUM_TO_STR(FLEX_BTN_PRESS_LONG_HOLD),
    ENUM_TO_STR(FLEX_BTN_PRESS_LONG_HOLD_UP),
    ENUM_TO_STR(FLEX_BTN_PRESS_MAX),
    ENUM_TO_STR(FLEX_BTN_PRESS_NONE),
};

static char *enum_btn_id_string[] =
{
    ENUM_TO_STR(USER_BUTTON_0),
    ENUM_TO_STR(USER_BUTTON_1),
    ENUM_TO_STR(USER_BUTTON_2),
    ENUM_TO_STR(USER_BUTTON_3),
    ENUM_TO_STR(USER_BUTTON_MAX),
};

static flex_button_t user_button[USER_BUTTON_MAX];

volatile static rt_thread_t tid1 = RT_NULL;

// 此函数需要实现，采用Emwin的KEY部分的发送
extern void WM_Send_Key_Msg(int Screen_Num, int Key, int Pressed, char Focus);
// example:
// void WM_Send_Key_Msg(char Screen_Num,int Key, int Pressed, char Focus)
// {
//     GUI_SendKeyMsg(Key, Pressed);
//     if (!Focus)
//         WM_SendMessageNoPara(WM_GetDialogItem(my_hWin, Screen_Num), WM_KEY_USER_DEAL);
// }

static void common_btn_evt_cb(void *arg)
{
    flex_button_t *btn = (flex_button_t *)arg;

    rt_kprintf( "id: [%d - %s]  event: [%d - %30s]  repeat: %d\n",
                btn->id, enum_btn_id_string[btn->id],
                btn->event, enum_event_string[btn->event],
                btn->click_cnt);
    switch (btn->id)
    {
    case  USER_BUTTON_0:
        switch (btn->event)
        {
        case FLEX_BTN_PRESS_CLICK:
            rt_kprintf("Button 0 is click!!\r\n");
#if WM_Enable
            WM_Send_Key_Msg(WM_Status.Current_Screen, GUI_KEY_RIGHT, 1, 0);
#endif
            break;

        default:
            break;
        }
        break;
    case  USER_BUTTON_1:
        switch (btn->event)
        {
        case FLEX_BTN_PRESS_CLICK:
            rt_kprintf("Button 1 is click!!\r\n");
#if WM_Enable
            WM_Send_Key_Msg(WM_Status.Current_Screen, GUI_KEY_DOWN, 1, 0);
#endif
            break;

        default:
            break;
        }
        break;
    case  USER_BUTTON_2:
        switch (btn->event)
        {
        case FLEX_BTN_PRESS_CLICK:
            rt_kprintf("Button 2 is click!!\r\n");
#if WM_Enable
            WM_Send_Key_Msg(WM_Status.Current_Screen, GUI_KEY_LEFT, 1, 0);
#endif
            break;

        default:
            break;
        }
        break;
    case  USER_BUTTON_3:
        switch (btn->event)
        {
        case FLEX_BTN_PRESS_CLICK:
            rt_kprintf("Button 3 is click!!\r\n");
            break;

        default:
            break;
        }
        break;
    default:
        break;
    }
    if ((flex_button_event_read(&user_button[USER_BUTTON_0]) == FLEX_BTN_PRESS_CLICK) && \
            (flex_button_event_read(&user_button[USER_BUTTON_1]) == FLEX_BTN_PRESS_CLICK))
    {
        rt_kprintf("[combination]: button 0 and button 1\n");
    }
}

/**
 * @function: scan_key_x_y
 * @brief: 行列式扫描按键
 * @param {*}
 * @return {*}
 * @author: lzc
 */
int scan_key_x_y(void)
{
    char key_x_num = 1;     //x轴
    char key_press_num = 0; //按下的按键，从k2开始
    int CC = 0; //用于标记按键信息
    /*X轴提供高电平*/
    while (1)
    {
        switch (key_x_num)
        {
        case 1:
            rt_pin_write(KEY_SCAN_Y1, PIN_LOW);
            rt_pin_write(KEY_SCAN_Y2, PIN_HIGH);
            break;
        case 2:
            rt_pin_write(KEY_SCAN_Y1, PIN_HIGH);
            rt_pin_write(KEY_SCAN_Y2, PIN_LOW);
            break;
        default:
            break;
        }
        for (int i = 0; i < 10; i++) {}
        /*read the state of Y1*/
        if (rt_pin_read(KEY_SCAN_X1) == 1)
        {
            CC |= 0x1 << key_press_num;
        }
        key_press_num++;
        if (rt_pin_read(KEY_SCAN_X2) == 1)
        {
            CC |= 0x1 << key_press_num;
        }
        key_press_num++;
        if (rt_pin_read(KEY_SCAN_X3) == 1)
        {
            CC |= 0x1 << key_press_num;
        }
        key_x_num++;
        key_press_num++;
        if (key_x_num >= 3)
        {
            rt_pin_write(KEY_SCAN_Y1, PIN_LOW);
            rt_pin_write(KEY_SCAN_Y2, PIN_LOW);
            return CC;
        }
    }
}

int Key_Value = 0;
static uint8_t common_btn_read(void *arg)
{
    uint8_t value = 0;
    flex_button_t *btn = (flex_button_t *)arg;
    Key_Value = 0;
    switch (btn->id)
    {
    case USER_BUTTON_0:
        // 如果是矩阵键盘
#if Matrix_keyboard_Enable
        Key_Value = scan_key_x_y();
        if (Key_Value == USER_MATRIX_BUTTON_0_Val)
            value = 1;
        else
            value = 0;
        // 普通按键
#else
        value =  rt_pin_read(KEY_0);
        Key_Value = value;
#endif
        break;

    case USER_BUTTON_1:
        // 如果是矩阵键盘
#if Matrix_keyboard_Enable
        Key_Value = scan_key_x_y();
        if (Key_Value == USER_MATRIX_BUTTON_1_Val)
            value = 1;
        else
            value = 0;
        // 普通按键
#else
        value = rt_pin_read(KEY_1);
        Key_Value = value;
#endif
        break;

    case USER_BUTTON_2:
        // 如果是矩阵键盘
#if Matrix_keyboard_Enable
        Key_Value = scan_key_x_y();
        if (Key_Value == USER_MATRIX_BUTTON_2_Val)
            value = 1;
        else
            value = 0;
        // 普通按键
#else
        value = rt_pin_read(KEY_2);
        Key_Value = value;
#endif
        break;

    case USER_BUTTON_3:
        // 如果是矩阵键盘
#if Matrix_keyboard_Enable
        Key_Value = scan_key_x_y();
        if (Key_Value == USER_MATRIX_BUTTON_3_Val)
            value = 1;
        else
            value = 0;
        // 普通按键
#else
        value = rt_pin_read(KEY_UP);
        Key_Value = value;
#endif
        break;
    default:
        RT_ASSERT(0);
    }
    return value;
}

static void user_button_init(void)
{
    int i;

    /* 初始化按键数据结构 */
    rt_memset(&user_button[0], 0x0, sizeof(user_button));

    rt_pin_mode(KEY_0, PIN_MODE_INPUT_PULLUP);
    rt_pin_mode(KEY_1, PIN_MODE_INPUT_PULLUP);
    rt_pin_mode(KEY_2, PIN_MODE_INPUT_PULLUP);
    rt_pin_mode(KEY_UP, PIN_MODE_INPUT_PULLUP);

    rt_pin_mode(KEY_SCAN_X1, PIN_MODE_INPUT);
    rt_pin_mode(KEY_SCAN_X2, PIN_MODE_INPUT);
    rt_pin_mode(KEY_SCAN_X3, PIN_MODE_INPUT);

    rt_pin_mode(KEY_SCAN_Y1, PIN_MODE_OUTPUT);
    rt_pin_mode(KEY_SCAN_Y2, PIN_MODE_OUTPUT);


    for (i = 0; i < USER_BUTTON_MAX; i ++)
    {
        user_button[i].id = i;
        user_button[i].usr_button_read = common_btn_read;
        user_button[i].cb = common_btn_evt_cb;
#if Matrix_keyboard_Enable
        user_button[i].pressed_logic_level = 1;
#else
        user_button[i].pressed_logic_level = 0;
#endif
        user_button[i].short_press_start_tick = FLEX_MS_TO_SCAN_CNT(1500);
        user_button[i].long_press_start_tick = FLEX_MS_TO_SCAN_CNT(3000);
        user_button[i].long_hold_start_tick = FLEX_MS_TO_SCAN_CNT(4500);

        if (i == USER_BUTTON_3)
        {
            user_button[USER_BUTTON_3].pressed_logic_level = 1;
        }

        flex_button_register(&user_button[i]);
    }
}

static void button_scan(void *arg)
{
    while (1)
    {
        flex_button_scan();
        rt_thread_mdelay(20); // 20 ms
    }
}

int flex_button_main(void)
{
    rt_thread_t tid = RT_NULL;
    user_button_init();
    /* 创建按键扫描线程 flex_btn，线程栈 1024 byte，优先级 10 */
    tid = rt_thread_create("flex_btn", button_scan, RT_NULL, 1024, 10, 10);
    if (tid != RT_NULL)
    {
        rt_thread_startup(tid);
    }
    return 0;
}

/* 使用 RT-Thread 的自动初始化 */
INIT_APP_EXPORT(flex_button_main);

